package view.impl;

import model.EMenuState;
import model.IViewModel;
import model.ModelFactory;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.Sound;

import view.IView;


/**
 *
 * Public singleton class that can be used by other packets to access and control
 * all the different parts of the view. Supplies methods to change to a specific
 * screen.
 *
 * @author Julian Lindblad 
 *
 */
public class View implements IView{
	private static final View INSTANCE = new View();
	
	private static final boolean MUSIC_ENABLED = true;
	
	private IViewState currentState = null;
	private EMenuState currentEState = null;
	
	private Sound menuMusic = null;
	private Sound gameMusic = null;
	private Sound backgroundMusic = null;
	
	/**
	 * Private constructor, as defined in Singleton-pattern.
	 */
	private View() {
		if(MUSIC_ENABLED) {
			try {
				menuMusic = new Sound("data/sound/Dubmood-Introchip.ogg");
				gameMusic = new Sound("data/sound/Dubmood-Afterburner.ogg");
				backgroundMusic = menuMusic;
			} catch (SlickException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * @return A singleton instance of MainMenuState.
	 */
	public static View getInstance() {
		return INSTANCE;
	}
	
	/**
	 * 
	 * Call this method to update and redraw the screen.
	 * 
	 * @param container 
	 * @param g
	 */
	@Override
	public void render(GameContainer container, Graphics g) throws RenderException {
		
		if(MUSIC_ENABLED && !backgroundMusic.playing()) {
			backgroundMusic.play();
		}
		
		changeState();
		currentState.render(g);
	}
	
	/**
	 * 
	 * Must be called when the controller/model changes the resolution, otherwise
	 * some parts of the rendering may not be correctly drawn.
	 * 
	 * @param targetWidth The target width on the resolution.
	 * @param targetHeight The target height on the resolution.
	 */
	@Override
	public void changeResolution(int targetWidth, int targetHeight) {
		currentState.changeResolution(targetWidth, targetHeight);
	}
	
	private void changeState() throws RenderException {
		IViewModel model = ModelFactory.getViewModel();
		if (currentEState != model.getEMenuState()) {
			currentEState = model.getEMenuState();
			switch (currentEState) {
			case MAIN_MENU:
				if(!isMenuState(currentState) && MUSIC_ENABLED) {
					backgroundMusic.stop();
					backgroundMusic = menuMusic;	// A quick background music implementation for the presentation.			
					backgroundMusic.play();			// Not by any means requirement for the project.
				}
				currentState = new MainMenuState();
				break;
			case SETTINGS:
				if(!isMenuState(currentState) && MUSIC_ENABLED) {
					backgroundMusic.stop();
					backgroundMusic = menuMusic;
					backgroundMusic.play();
				}
				currentState = new SettingsMenuState();
				break;
			case CHARACTER_SELECTION:
				if(!isMenuState(currentState) && MUSIC_ENABLED) {
					backgroundMusic.stop();
					backgroundMusic = menuMusic;
					backgroundMusic.play();
				}
				currentState = new CharSelectState();
				break;
			case CONNECTING:
				if(MUSIC_ENABLED) {
					backgroundMusic.stop();
				}
				currentState = new ConnectingState();
				break;
			case IN_GAME:
				if(MUSIC_ENABLED) {
					backgroundMusic.stop();
					backgroundMusic = gameMusic;
					backgroundMusic.play();
				}
				currentState = new InGameState();
			default:
				break;
			}
		}
	}
	
	private boolean isMenuState(IViewState state) {
		if(state == null)
			return false;
		
		return state.getEMenuTyoe() == EMenuState.MAIN_MENU ||
			   state.getEMenuTyoe() == EMenuState.SETTINGS  ||
			   state.getEMenuTyoe() == EMenuState.CHARACTER_SELECTION;
	}
}
